package com.atguigu.tingshu.common.aspect;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.AuthLogin;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * Author  王东剑
 * Created on 6/6/2024 PM5:26
 * Package_name com.atguigu.tingshu.common.aspect
 * Description
 */
@Slf4j
@Aspect
@Component
public class GuiGuLoginAspect {
	@Autowired
	private StringRedisTemplate redisTemplate;
	@Around("@annotation(authLogin)")
	public Object around(ProceedingJoinPoint joinPoint, AuthLogin authLogin){
		// 1.是否需要校验
		// 2.需要校验,获取token
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		String token = requestAttributes.getRequest().getHeader("token");
		if(authLogin.required()){
			// 3.token是否为空
			if(StringUtils.isEmpty(token))
				throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
			// 4.token获取redis数据是否为空
			String redisTokenKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
			String userInfoJson = redisTemplate.opsForValue().get(redisTokenKey);
			if(StringUtils.isEmpty(userInfoJson))
				throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
			// 5.将数据保存到 AuthContextHolder 里面
			this.setAuthContextHolder(userInfoJson);
		}else{
			// 6.不要验证时,如果token不为空 就去获取redis数据
			if(!StringUtils.isEmpty(token)){
				String redisTokenKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
				String userInfoJson = redisTemplate.opsForValue().get(redisTokenKey);
				// 7.如果redis数据不为空,就去将数据保存到 AuthContextHolder 里面
				if(!StringUtils.isEmpty(userInfoJson))
					this.setAuthContextHolder(userInfoJson);
			}
		}
		try{
			// 8.执行方法
			// 9.返回结果数据
			return joinPoint.proceed();
		}catch (Throwable e){
			e.printStackTrace();
			if(e instanceof GuiguException)
				throw (GuiguException)e;
			throw new RuntimeException(e);
		}finally {
			// 10.释放资源
			AuthContextHolder.removeUserId();
			AuthContextHolder.removeUsername();
		}
	}

	private void setAuthContextHolder(String userInfoJson){
		UserInfo userInfo = JSON.parseObject(userInfoJson, UserInfo.class);
		AuthContextHolder.setUserId(userInfo.getId());
		AuthContextHolder.setUsername(userInfo.getNickname());
	}
}
